package com.ctrip.payment.config;

import com.ctrip.payment.properties.DataSourceProperties;
import com.ctrip.payment.properties.HibernateProperties;
import com.ckjava.xutils.StringUtils;
import com.zaxxer.hikari.HikariDataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;
import java.util.Properties;

@Configuration
@EnableJpaRepositories(basePackages = "com.ctrip.payment",
        entityManagerFactoryRef = "entityManagerFactory",
        transactionManagerRef = "transactionManager")
@EnableTransactionManagement
public class JpaConfig {

    private static final String basePackages = "com.ctrip.payment";

    @Autowired
    private DataSourceProperties dataSourceProperties;
    @Autowired
    private HibernateProperties hibernateProperties;

    /*
     * 配置 HikariCP 连接池数据源.
     */
    @Bean
    public DataSource debugDataSource() {
        HikariDataSource dataSource = (HikariDataSource) DataSourceBuilder
                .create(dataSourceProperties.getClassLoader())
                .driverClassName(dataSourceProperties.getDriverClassName())
                .url(dataSourceProperties.getUrl())
                .username(dataSourceProperties.getUsername())
                .password(dataSourceProperties.getPassword())
                .type(HikariDataSource.class)
                .build();    
        dataSource.setMaximumPoolSize(dataSourceProperties.getMaxPoolSize());
        return dataSource;
    }

    /*
     * Entity Manager Factory 配置.
     */
    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory() throws Exception {
        LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();
        factoryBean.setDataSource(debugDataSource());
        factoryBean.setPackagesToScan(new String[]{basePackages});
        factoryBean.setJpaVendorAdapter(jpaVendorAdapter());
        factoryBean.setJpaProperties(jpaProperties());
        return factoryBean;
    }

    /**
     * 指定 hibernate 为 jpa 的持久化框架
     * @return
     */
    @Bean
    public JpaVendorAdapter jpaVendorAdapter() {
        HibernateJpaVendorAdapter hibernateJpaVendorAdapter = new HibernateJpaVendorAdapter();
        return hibernateJpaVendorAdapter;
    }

    /*
     * 读取 hibernate 相关配置
     */
    private Properties jpaProperties() {
        Properties properties = new Properties();
        properties.put("hibernate.dialect", hibernateProperties.getDialect());
        properties.put("hibernate.hbm2ddl.auto", hibernateProperties.getHbm2ddl_auto());
        properties.put("hibernate.show_sql", hibernateProperties.getShow_sql());
        properties.put("hibernate.format_sql", hibernateProperties.getFormat_sql());
        if (StringUtils.isNotEmpty(dataSourceProperties.getDefaultSchema())) {
            properties.put("hibernate.default_schema", dataSourceProperties.getDefaultSchema());
        }
        return properties;
    }

    @Bean
    public PlatformTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
        JpaTransactionManager txManager = new JpaTransactionManager();
        txManager.setEntityManagerFactory(entityManagerFactory);
        return txManager;
    }
}
